const ioredis = require('ioredis');
const nodeIp = require('ip');
const WebSocket = require('ws');
const model = require('./models/model'); //查询方法
const tool = require('./utility/tool'); //公共工具
const Long = require('mongodb').Long; //bson数据格式调用
//初始化连接本地redis
const server = require('./config/server'); //配置文件
const redisUrl = 'redis://:' + server.redis.user + ':' + server.redis.pwd + '@' + server.redis.host + ':' + server.redis.port + '/' + server.redis.db;
global.redis = new ioredis(redisUrl);

//初始化连接数据库
var MongoClient = require('mongodb').MongoClient;
var mongodb = 'mongodb://' + server.mongodb.user +
    ':' +
    server.mongodb.password +
    '@' + server.mongodb.host +
    ':' + server.mongodb.port +
    '/' +
    server.mongodb.database +
    '?authMechanism=' +
    server.mongodb.authMechanism +
    '&authSource=' +
    server.mongodb.authSource; //数据库地址
MongoClient.connect(mongodb, {
    useNewUrlParser: true
}, function(err, client) {
    if (err) throw err;
    let db = client.db(server.mongodb.database);
    global.db = client.db(server.mongodb.database); //注册mongodb
});

/**
 * @api {post} /soc/msg 适时消息获取
 * @apiVersion 0.1.0
 * @apiGroup soc
 * @apiName ws/soc/msg0.1.0soc
 * @apiDescription 注：通过websocket获取实时消息
 * @apiPermission 操作员权限
 * @apiParam (参数param) {Object} param 参数
 * @apiParamExample {json} 参数书写方法:
     this.websock.send('请求数据');
 * @apiExample 请求示例:
     initWebSocket(){ //初始化weosocket
         const wsuri = "ws://127.0.0.1:3001/soc/msg";
         this.websock = new WebSocket(wsuri);
         this.websock.onopen = this.websocketonopen;
         this.websock.onmessage = this.websocketonmessage;
         this.websock.onerror = this.websocketonerror;
         this.websock.onclose = this.websocketclose;
     },
     websocketonopen(){ //连接建立之后执行send方法发送数据
         this.websock.send('请求数据');
     },
     websocketonmessage(data){ //数据接收
         console.log('message',data);
         //数组长度判定
         if(this.websockMsgs.length < 5){
             this.websockMsgs.unshift(data.data);//把后端数据追加到数组开头
         }else{
             this.websockMsgs.pop();//删除数组最后一个值
             this.websockMsgs.unshift(data.data);//把后端数据追加到数组开头
         }
     },
     websocketonerror(){//连接建立失败重连
         this.initWebSocket();
     },
     websocketclose(e){  //关闭
         console.log('断开连接',e);
     },
 * @apiSuccess (成功 200) {Number} status 200:表示成功
 * @apiSuccess (成功 200) {Number} data 成功后数据
 * @apiSuccess (成功 200) {Number} data.data 表示成功后返回的数据【被序列化的数据（字符串）】
 * @apiSuccess (成功 200) {Array} data.eventtype 事件类型【外联类事件固定值：outreach】
 * @apiSuccess (成功 200) {Array} data.eventid 外联事件日志ID
 * @apiSuccess (成功 200) {Array} data.outreachid 非法外联日志ID
 * @apiSuccess (成功 200) {Array} data.shortname 站点简称
 * @apiSuccess (成功 200) {Array} data.describe 事件描述
 * @apiSuccess (成功 200) {Array} data.ctime 事件发生时间
 * @apiSuccess (成功 200) {Array} data.warnlevel 预警等级
 * @apiSuccessExample {json} 成功后返回:
    {
        bubbles: false
        cancelBubble: false
        cancelable: false
        composed: false
        currentTarget: WebSocket {url: "ws://127.0.0.1:3001/soc/msg", readyState: 3, bufferedAmount: 0, onopen: ƒ, onerror: ƒ, …}
        data: "{"eventtype":"outreach","eventid":"5c4ecd58098f6b3e595b19da","outreachid":"5c4ecd58098f6b3e595b19d9","shortname":"济南市历下区龙洞变","describe":"热点设备接入异常（外联预警）！","ctime":"2019-1-28 17:37:28","warnlevel":"1"}"
        defaultPrevented: false
        eventPhase: 0
        isTrusted: true
        lastEventId: ""
        origin: "ws://127.0.0.1:3001"
        path: []
        ports: []
        returnValue: true
        source: null
        srcElement: WebSocket {url: "ws://127.0.0.1:3001/soc/msg", readyState: 3, bufferedAmount: 0, onopen: ƒ, onerror: ƒ, …}
        target: WebSocket {url: "ws://127.0.0.1:3001/soc/msg", readyState: 3, bufferedAmount: 0, onopen: ƒ, onerror: ƒ, …}
        timeStamp: 218553.89999999898
        type: "message"
    }
 * @apiError (失败 4xx) data 失败时不返回数据【注意】
 * @apiErrorExample {json} 失败返回值:
    {}
 */
//引用Server类:
let wss = new WebSocket.Server({
    port: 3001,
    path: '/soc/msg'
});
//响应connection事件来处理WebSocket
wss.on('connection', (ws, req) => {
    ws.on('message', async (message) => {
        while (true) {
            let callback = {},
                param = {}; //定义前端返回值和插入数据库的值
            let listBlpop = await global.redis.blpop("center_warner_rcver_l", 0); //获取redis阻塞数据
            let listBlpopStr = new Buffer(listBlpop[1], 'base64').toString(); //base64转字符串
            if (listBlpopStr) { //判定有无数据
                let listBlpopObj = JSON.parse(listBlpopStr); //反序列化数据
                //处理数据格式
                for (let i in listBlpopObj) {
                    if (i == 'ctime') {
                        let unIp = nodeIp.fromLong(listBlpopObj[i]); //获取当前数据ip
                        let ipArr = unIp.split(".");
                        ipArr.reverse(); //颠倒数组顺序
                        let ipStr = ipArr.join('.'); //把ip数组转换成字符串
                        callback[i] = String(ipStr) //识别设备的IP地址
                        param[i] = Long.fromNumber(listBlpopObj[i]); //把返回值的时间戳格式化
                    } else {
                        callback[i] = String(listBlpopObj[i]); //把数据赋值给返回值
                        param[i] = String(listBlpopObj[i]); //把数据赋值给返回值
                    };
                };
                let insertOne = await model.insertOne(param, "temp_news"); //插入数据库方法调用
                //构造返回值
                if (insertOne) {
                    console.log(`[SERVER] Received: ${message}`);
                    wss.clients.forEach((client) => {
                        client.send(JSON.stringify(callback));
                    });
                };
            };
        };
    });
});